package collage;

import java.awt.*;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;

/**
 *
 * @author Mark
 */
public class InputController implements MouseListener, MouseMotionListener,
        KeyListener, MouseWheelListener {

    JPanel mp = null;
    CollageView cv = null;
    Point mouseStart = null;
    boolean resizing = false;
    Toolkit toolkit = Toolkit.getDefaultToolkit();    
    Image image = toolkit.getImage("src/collage/resources/rotate.gif");      
    Point hotSpot = new Point(15, 15);
    Cursor customCursor = toolkit.createCustomCursor(image, hotSpot, "Rotate");
    private JPopupMenu contextMenu;
    
    InputController(JPanel mp, CollageView cv, JPopupMenu contextMenu) {
        this.mp = mp;
        this.cv = cv;
        this.contextMenu = contextMenu;
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        if (mp.getCursor().getType() == Cursor.DEFAULT_CURSOR) {
            if (!e.isShiftDown()) {
                for (Component c1 : mp.getComponents()) {
                    if (c1 instanceof ImagePanel) {
                        ((ImagePanel) c1).selected = false;
                    }
                }
            }
            Component c2 = mp.getComponentAt(e.getPoint());
            if (c2 instanceof ImagePanel) {
                ((ImagePanel) c2).selected = true;
            }
            mp.repaint();
        }
        mouseStart = e.getPoint();
    }

    public void mouseReleased(MouseEvent e) {

        for (Component c : mp.getComponents()) {
            if (c instanceof ImagePanel) {
                ImagePanel ip = ((ImagePanel) c);
                if (ip.selected) {
                    if (resizing) {
                        ip.updateImage();
                        resizing = false;
                        mp.repaint();
                    } else if (e.isPopupTrigger() && !e.isShiftDown()) {
                        //TODO: this should have been an ImagePlane mouse listener; not here
                        ip.selected = true;
                        contextMenu.show(e.getComponent(), e.getX(), e.getY());

                    }
                }
            }
        }

    }

    public void mouseDragged(MouseEvent e) {
        Point mouseEnd = e.getPoint();
        for (Component c : mp.getComponents()) {
            if (c instanceof ImagePanel) {
                ImagePanel ip = ((ImagePanel) c);
                if (ip.selected) {
                    Point ipLoc = ip.getLocation();
                    int dx = mouseEnd.x - mouseStart.x;
                    int dy = mouseEnd.y - mouseStart.y;
                    if (mp.getCursor().getType() == Cursor.DEFAULT_CURSOR) {
                        ip.setLocation(dx + ipLoc.x, dy + ipLoc.y);
                    } else {
                        if (mp.getCursor().getType() == Cursor.NW_RESIZE_CURSOR) {
                            ip.setBounds(ipLoc.x + dx, ipLoc.y + dy,
                                    ip.getWidth() - dx, ip.getHeight() - dy);
                        } else if (mp.getCursor().getType() == Cursor.NE_RESIZE_CURSOR) {
                            ip.setBounds(ipLoc.x, ipLoc.y + dy,
                                    ip.getWidth() + dx, ip.getHeight() - dy);
                        } else if (mp.getCursor().getType() == Cursor.SW_RESIZE_CURSOR) {
                            ip.setBounds(ipLoc.x + dx, ipLoc.y,
                                    ip.getWidth() - dx, ip.getHeight() + dy);
                        } else if (mp.getCursor().getType() == Cursor.SE_RESIZE_CURSOR) {
                            ip.setBounds(ipLoc.x, ipLoc.y,
                                    ip.getWidth() + dx, ip.getHeight() + dy);
                        }
                        ip.quickUpdate();
                        resizing = true;
                        mp.repaint();
                    }
                }
            }
        }
        mouseStart = e.getPoint();
    }

    public void mouseMoved(MouseEvent e) {

        Point p = e.getPoint();
        double maxDist = 7.5;
        double maxRotationDist = 25.0;
        boolean change = false;
        for (Component c : mp.getComponents()) {
            if (c instanceof ImagePanel) {
                ImagePanel ip = ((ImagePanel) c);
                if (ip.selected) {
                    if (dist(p, ip.getLocation()) < maxDist) {
                        mp.setCursor(new Cursor(Cursor.NW_RESIZE_CURSOR));
                        change = true;
                    } else if (dist2(p, new Point(ip.getX() + ip.getWidth(), ip.getY())) < maxDist) {
                        mp.setCursor(new Cursor(Cursor.NE_RESIZE_CURSOR));
                        change = true;
                    } else if (dist(p, new Point(ip.getX(), ip.getY() + ip.getHeight())) < maxDist) {
                        mp.setCursor(new Cursor(Cursor.SW_RESIZE_CURSOR));
                        change = true;
                    } else if (dist(p, new Point(ip.getX() + ip.getWidth(), ip.getY() + ip.getHeight())) < maxDist) {
                        mp.setCursor(new Cursor(Cursor.SE_RESIZE_CURSOR));
                        change = true;
                    } else if (dist(p, ip.getLocation()) >= maxDist && dist(p, ip.getLocation()) < maxRotationDist) {
                        mp.setCursor(customCursor);
                        change = true;
                    } else if (dist2(p, new Point(ip.getX() + ip.getWidth(), ip.getY())) >= maxDist && dist2(p, new Point(ip.getX() + ip.getWidth(), ip.getY())) < maxRotationDist) {
                        mp.setCursor(customCursor);
                        change = true;
                    } else if (dist3(p, new Point(ip.getX(), ip.getY() + ip.getHeight())) >= maxDist && dist3(p, new Point(ip.getX(), ip.getY() + ip.getHeight())) < maxRotationDist) {
                        mp.setCursor(customCursor);
                        change = true;
                    } else if (dist4(p, new Point(ip.getX() + ip.getWidth(), ip.getY() + ip.getHeight())) >= maxDist && dist4(p, new Point(ip.getX() + ip.getWidth(), ip.getY() + ip.getHeight())) < maxRotationDist) {
                        mp.setCursor(customCursor);
                        change = true;
                    }
                }
            }
        }
        if (!change) {
            mp.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
    }

    private double dist(Point p1, Point p2) {
        int dx = p2.x - p1.x;
        int dy = p2.y - p1.y;
        if (dx < 0 && dy < 0) {
            return 100;
        } else {
            return Math.sqrt(dx * dx + dy * dy);
        }
    }

    private double dist2(Point p1, Point p2) {
        int dx = p2.x - p1.x;
        int dy = p2.y - p1.y;
        if (dx > 0 && dy < 0) {
            return 100;
        } else {
            return Math.sqrt(dx * dx + dy * dy);
        }
    }

    private double dist3(Point p1, Point p2) {
        int dx = p2.x - p1.x;
        int dy = p2.y - p1.y;
        if (dx < 0 && dy > 0) {
            return 100;
        } else {
            return Math.sqrt(dx * dx + dy * dy);
        }
    }

    private double dist4(Point p1, Point p2) {
        int dx = p2.x - p1.x;
        int dy = p2.y - p1.y;
        if (dx > 0 && dy > 0) {
            return 100;
        } else {
            return Math.sqrt(dx * dx + dy * dy);
        }
    }

    public void mouseWheelMoved(MouseWheelEvent e) {
        int minZ = 1000, maxZ = -1000;
        int notches = e.getWheelRotation();

        for (Component c : mp.getComponents()) {
            if (c instanceof ImagePanel) {
                ImagePanel ip = ((ImagePanel) c);
                int z = mp.getComponentZOrder(ip);
                if (z < minZ) {
                    minZ = z;
                }
                if (z > maxZ) {
                    maxZ = z;
                }
            }
        }

        for (Component c : mp.getComponents()) {
            if (c instanceof ImagePanel) {
                ImagePanel ip = ((ImagePanel) c);
                if (ip.selected) {
                    int z = mp.getComponentZOrder(ip);
                    z -= notches;
                    if (z > maxZ) {
                        z = maxZ;
                    }
                    if (z < minZ) {
                        z = minZ;
                    }
                    mp.setComponentZOrder(ip, z);
                }
            }
        }
        mp.repaint();
    }

    public void keyPressed(KeyEvent e) {
        int kc = e.getKeyCode();
        if (kc == KeyEvent.VK_DELETE || kc == KeyEvent.VK_BACK_SPACE) {
            cv.removeImages();
        }
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyTyped(KeyEvent e) {
    }

    public void alert(String msg) {
        JOptionPane.showMessageDialog(null, msg);
    }
}
